#pragma once
#ifndef NULL
	#define NULL 0
#endif

template<typename TYPE>
class Vector
{
protected:
	TYPE*		m_xList;
	int			m_iAllocated;
	int			m_iSize;
	const int	m_iAllocateBy;
	void allocate()
	{
		if(m_xList == NULL || m_iAllocated == 0)
			m_xList = new TYPE[m_iAllocated+=m_iAllocateBy];
		else if(m_iSize >= m_iAllocated)
		{
			TYPE* tempList = new TYPE[m_iAllocated+=m_iAllocateBy];
			for(int i = 0; i < m_iSize; ++i)
				tempList[i] = m_xList[i];
			delete [] m_xList;
			m_xList = tempList;
		}
	}
public:
	Vector()
		: m_xList(NULL)
		, m_iAllocated(0)
		, m_iSize(0)
		, m_iAllocateBy(20)
	{}

	// adds value to the end of the list
	int push(TYPE toAdd)	
	{
		allocate();
		m_xList[m_iSize++] = toAdd;

		return m_iSize-1;
	}
	bool insert(TYPE toAdd, int index)
	{
		if(index >= m_iSize)
			return false;

		allocate();
		// move everything from the index on back by one
		for(int i = m_iSize; i >= index; --i)
		{
			m_xList[i+1] = m_xList[i];
		}
		m_xList[index] = toAdd;
		m_iSize++;
		return true;
	}
	bool remove(int index)
	{
		if(index >= m_iSize || index < 0)
			return false;

		// move everything in the list back by one
		for(int i = index; i < m_iSize-1; ++i)
		{
			m_xList[i] = m_xList[i+1];
		}
		m_iSize--;
		return true;
	}

	TYPE &getByIndex(int index) 
	{
		if(index >= m_iSize || index < 0)
			return m_xList[0];

		return m_xList[index];
	}

	void clear()
	{
		if(m_xList != NULL)
			delete [] m_xList;
		m_xList = NULL;
		m_iAllocated = m_iSize = 0;
	}

	TYPE &operator[](int index) { return getByIndex(index); }
	TYPE &getFirst(int index) { return getByIndex(0); }
	TYPE &getLast(int index) { return getByIndex(m_iSize-1); }
	int size() { return m_iSize; }
};